/*
 * XTask.java
 * 
 * Copyright (c) 2006 - 2007
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.xfc.util;

import java.beans.PropertyChangeListener;

import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.xfc.XApp;
import org.xfc.dialog.XErrorDialog;
import org.xfc.model.XObject;

/**
 * 
 * 
 * @author Devon Carew
 */
public abstract class XTask
	implements XJavaBean
{
	private static ImageIcon DEFAULT_TASK_ICON = XApp.getApp().getResources().getIcon("/eclipse/org.eclipse.ui/icons/full/obj16/taskmrk_tsk.gif");
	
	private XObject	properties = new XObject();
	
	private long	startTime = -1;
	private long	endTime = -1;
	
	/**
	 * @param taskName
	 */
	public XTask(String taskName)
	{
		this(taskName, null);
	}
	
	/**
	 * @param taskName
	 * @param icon
	 */
	public XTask(String taskName, Icon icon)
	{
		setTaskName(taskName);
		setIcon(icon != null ? icon : XTask.getDefaultTaskIcon());
	}
	
	/**
	 * Schedules the task.
	 */
	public final void start()
	{
		XTaskManager.getTaskManager().scheduleTask(this);
	}
	
	/**
	 * Called on the event thread before the task starts. Returning false cancels the task.
	 * 
	 * @return Return whether to continue executing the task.
	 */
	protected boolean taskPreFlight()
	{
		return true;
	}
	
	/**
	 * Called on a non-event thread. The main body of the task's work is performed here.
	 * 
	 * @return Returns the result of the task. May be null.
	 */
	protected abstract Object performWork()
		throws Exception;
	
	/**
	 * Called on the event thread. The Object parameter is the result from the performWork() method.
	 * 
	 * @param result
	 */
	protected void taskPostFlightSuccess(Object result)
	{
		
	}

	/**
	 * Called on the event thread. The Throwable parameter is exception thrown from the performWork() method.
	 * The default implmentation of this method displays the error in a dialog.
	 * 
	 * @param t
	 */
	protected void taskPostFlightException(Throwable t)
	{
		XErrorDialog.showError(getTaskName(), t);
	}
	
	public boolean isCancelable() {
		return properties.getValueAsBoolean("cancelable");
	}

	public void setCancelable(boolean cancelable) {
		properties.setValue("cancelable", cancelable);
	}
	
	public boolean isCancelled() {
		return properties.getValueAsBoolean("cancelled");
	}

	public void setCancelled(boolean cancelled) {
		properties.setValue("cancelled", cancelled);
	}

	public Icon getIcon() {
		return (Icon)properties.getValue("icon");
	}

	public void setIcon(Icon icon) {
		properties.setValue("icon", icon);
	}

	public boolean isModal() {
		return properties.getValueAsBoolean("modal");
	}

	public void setModal(boolean modal) {
		properties.setValue("modal", modal);
	}

	public String getTaskName() {
		return (String)properties.getValue("taskName");
	}

	public void setTaskName(String taskName) {
		properties.setValue("taskName", taskName);
	}
	
	public long getElapsedTime()
	{
		if (endTime != -1)
			return endTime - startTime;
		
		if (startTime != -1)
			return System.currentTimeMillis() - startTime;
		
		return 0;
	}
	
	public boolean isTaskRunning()
	{
		return startTime != -1 && endTime == -1;
	}
	
	final void taskWasStarted()
	{
		startTime = System.currentTimeMillis();
		
		properties.setValue("taskRunning", isTaskRunning());
	}
	
	final void taskWasStopped()
	{
		endTime = System.currentTimeMillis();
		
		properties.setValue("taskRunning", isTaskRunning());
	}
	
	public static Icon getDefaultTaskIcon()
	{
		return DEFAULT_TASK_ICON;
	}

	public void addPropertyChangeListener(PropertyChangeListener listener)
	{
		properties.addPropertyChangeListener(listener);
	}

	public void removePropertyChangeListener(PropertyChangeListener listener)
	{
		properties.removePropertyChangeListener(listener);
	}
	
}
